<!DOCTYPE html>
<head>
<title>Urchin Data API</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>The Urchin Software Data API Visualization Sample</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  google.load('visualization', '1', {'packages': ['annotatedtimeline']});
  google.setOnLoadCallback(run);

  gAnnotations = null;

  function run() {
    resetAll();
    document.getElementById("progress").innerHTML = '...' ;

    // retrieve annotations
    var query = new google.visualization.Query('http://spreadsheets.google.com/tq?range=A1:C12&headers=-1&key=pLWL2CeXljj7vPVT4EtzeZQ&gid=8');
    query.send(handleRequest);
  }

  function handleRequest(response) {
    if (response.isError()) {
      uerror("Failed to read annotations from the external spreadsheet.");
      uerror(response.getMessage());
      uerror(response.getDetailedMessage());
    }

    gAnnotations = response;

    // retrieve totals
    url = document.URL.substring(0, document.URL.lastIndexOf('/') + 1) +
          "services/v1/reportservice/data?" +
          "login=" + document.args.login.value + "&" +
          "password=" + document.args.password.value + "&" +
          "ids=" + document.args.ids.value + "&" +
          "start-date=" + document.args.startdate.value + "&" +
          "end-date=" + document.args.enddate.value + "&" +
          "max-results=1000&" +
          "dimensions=u:day&metrics=u:hits,u:pages,u:visits,u:transactions,u:avgsessiontime";

    // create xmlhttprequest object
    if (window.XMLHttpRequest) {
      xmlhttp = new XMLHttpRequest();

      // make sure that Browser supports overrideMimeType
      if (typeof xmlhttp.overrideMimeType != 'undefined') {
          xmlhttp.overrideMimeType('text/xml');
      }
    } else if (window.ActiveXObject) {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }  else {
      uerror('Perhaps your browser does not support xmlhttprequests?');
    }

    // create an HTTP GET request
    xmlhttp.open('GET', url, true);

    // set the callback function
    xmlhttp.onreadystatechange = checkXmlHttpStateChange;

    // make the actual request
    xmlhttp.send(null);
  }

  function checkXmlHttpStateChange() {
    if (xmlhttp.readyState == 4) {
      if (xmlhttp.status == 200) {
          udebug("checkXmlHttpStateChange: response = [" + xmlhttp.responseText + "]");

          // parse XML
          try { // IE
            xmlDocument = new ActiveXObject("Microsoft.XMLDOM");
            xmlDocument.async = "false";
            xmlDocument.loadXML(xmlhttp.responseText);
          }
          catch(e) {
            try { // Firefox, Mozilla, Opera, etc.
                domParser = new DOMParser();
                xmlDocument = domParser.parseFromString(xmlhttp.responseText, "application/xml");
            }
            catch(e) {
                alert(e.message)
            }
          }

          var parseError = checkForParseError(xmlDocument);
          if (parseError.errorCode == 0) {
            // draw resulting table
            if (draw(xmlDocument) <= 0) return;
          }
          else {
            uerror("checkXmlHttpStateChange: error while parsing response. " +
                   "code: " + parseError.errorCode + ", " +
                   "reason: " + parseError.reason);
          }
      }
      else {
        uerror("checkXmlHttpStateChange: xmlhttp.status:" + xmlhttp.status +
               ", xmlhttp.responseText:" + xmlhttp.responseText);
      }
    }
  }

  function checkForParseError(xmlDocument) {
    var errorNamespace ='http://www.mozilla.org/newlayout/xml/parsererror.xml';
    var documentElement = xmlDocument.documentElement;
    var parseError = { errorCode : 0 };
    if (documentElement.nodeName == 'parsererror' && documentElement.namespaceURI == errorNamespace) {
      parseError.errorCode = 1;
      var sourceText = documentElement.getElementsByTagNameNS(errorNamespace, 'sourcetext')[0];
      if (sourceText != null) {
        parseError.srcText = sourceText.firstChild.data
      }
      parseError.reason = documentElement.firstChild.data;
    }
    return parseError;
  }

  function draw(xmlDocument) {
    if (!xmlDocument || !gAnnotations) {
      uerror("internal error.");
      return -1;
    }

    // get annotations
    var annotationsData = gAnnotations.getDataTable();

    // get the XML root item
    var root = xmlDocument.firstChild;

    var urchinData = new google.visualization.DataTable();

    // add rows and columns
    urchinData.addRows(root.childNodes.length);

    urchinData.addColumn("date", "Date");
    urchinData.addColumn("number", "Hits");
    urchinData.addColumn("string", "Annotation column 1");
    urchinData.addColumn("string", "Annotation text column 1");
    urchinData.addColumn("number", "Pages");
    urchinData.addColumn("number", "Visits");
    urchinData.addColumn("number", "Transactions");
    urchinData.addColumn("number", "Average session length");

    var re = /(-)?(\d{4})-(\d{2})-(\d{2})(T(\d{2}):(\d{2}):(\d{2})(\.\d+)?)Z(([\+-])((\d{2}):(\d{2})))?/;

    // set data
    for (var row_idx = 0; row_idx < root.childNodes.length; row_idx++) {
      // dimensions
      var dRoot = root.childNodes.item(row_idx).childNodes.item(1);
      var dDate = new Date(dRoot.childNodes.item(0).firstChild.data.replace(re, "$3/$4/$2 $6:$7:$8"));
      urchinData.setValue(row_idx, 0, dDate);

      // metrics
      var mRoot = root.childNodes.item(row_idx).childNodes.item(2);
      urchinData.setValue(row_idx, 1, parseInt(mRoot.childNodes.item(0).firstChild.data));
      urchinData.setValue(row_idx, 4, parseInt(mRoot.childNodes.item(1).firstChild.data));
      urchinData.setValue(row_idx, 5, parseInt(mRoot.childNodes.item(2).firstChild.data));
      urchinData.setValue(row_idx, 6, parseInt(mRoot.childNodes.item(3).firstChild.data));
      urchinData.setValue(row_idx, 7, parseInt(mRoot.childNodes.item(4).firstChild.data));

      // annotations
      for (var aidx = 0; aidx < annotationsData.getNumberOfRows(); aidx++) {
        if (dDate.getTime() == annotationsData.getValue(aidx, 0).getTime()) {
          urchinData.setValue(row_idx, 2, annotationsData.getValue(aidx, 1));
          urchinData.setValue(row_idx, 3, annotationsData.getValue(aidx, 2));
          break;
        }
      }
    }

    var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
    chart.draw(urchinData, {displayAnnotations: true});

    document.getElementById("progress").innerHTML = 'done' ;

    return root.childNodes.length;
  }

  function udebug(msg) {
    if (!msg || msg == "") return;
    document.getElementById("debug_div").style.display = '' ;
    document.getElementById("debugarea").value += "DEBUG: " + msg + "\n";
  }

  function uerror(msg) {
    if (!msg || msg == "") return;
    document.getElementById("progress").innerHTML = 'error' ;
    document.getElementById("error_div").style.display = '' ;
    document.getElementById("errorarea").value += "ERROR: " + msg + "\n";
  }

  function resetAll() {
    document.getElementById("error_div").style.display = 'none' ;
    document.getElementById("debug_div").style.display = 'none' ;
    document.getElementById("debugarea").value = "";
    document.getElementById("errorarea").value = "";
  }
</script>

</head>

<body  onLoad="resetAll()">
  <H2>The Urchin Software Data API Visualization Sample</H2>
  <p>Processed data is extracted thru the <a href="https://secure.urchin.com/helpwiki/en/Data_API">Urchin Data API</a>, merged with annotations from the <a href="http://spreadsheets.google.com/tq?range=A1:C12&headers=-1&key=pLWL2CeXljj7vPVT4EtzeZQ&gid=8">Google spreadsheets</a>
  and visualized via annotated timeline from the <a href="http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html">Google Visualization API</a>.
  <br>To deploy simply copy timeline.html to Urchin htdocs directory.</p>
  <form id="args" name="args" action="" method="get">
    <table>
      <tr>
        <td width=50%>login*</td>
        <td width=50%><input alt="login" name="login" type="text" size="20" maxlength="64" value="admin"></td>
      </tr>
      <tr>
        <td width=50%>password*</td>
        <td width=50%><input alt="password" name="password" type="text" size="20" maxlength="64" value="urchin"></td>
      </tr>
      <tr>
        <td width=50%>profileId*</td>
        <td width=50%><input alt="profileId" name="ids" type="text" size="20" maxlength="64" value="1"></td>
      </tr>
      <tr>
        <td width=50%>start-date(yyyy-mm-dd)*</td>
        <td width=50%><input alt="start-date" name="startdate" type="text" size="20" maxlength="64" value="2009-01-01"></td>
      </tr>
      <tr>
        <td width=50%>end-date(yyyy-mm-dd)*</td>
        <td width=50%><input alt="end-date" name="enddate" type="text" size="20" maxlength="64" value="2010-01-01"></td>
      </tr>
      <tr>
        <td><input type="button" value="Go!" onclick="run()"></td>
        <td><div id="progress"></td>
      </tr>
    </table>
  </form>
  <div id="chart_div" style="width: 1000px; height: 400px;"></div>
  <div id="error_div" width=100%>
    <H3>Error</H3>
    <textarea rows=10 style="width: 100%;" id="errorarea"></textarea>
  </div>
  <div id="debug_div" width=100%>
    <H3>Debug</H3>
    <textarea rows=10 style="width: 100%;" id="debugarea"></textarea>
  </div>
</body>
</html>
